﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Globalization;
using System.Web;
using System.Xml;
using System.Drawing;

namespace WowGuildSite.Armory
{
    public enum ArmoryServerRegion
    {
        Europe,
        Usa,
    }

    public sealed class ArmoryServerDataSource : IArmoryDataSource
    {
        private CultureInfo         culture;
        private ArmoryServerRegion  region;
        private string              realmName;
        private string              debugPath;

        private string              ServerUrl
        {
            get
            {
                switch (region)
                {
                    case ArmoryServerRegion.Europe:
                        return "http://armory.wow-europe.com";
                    case ArmoryServerRegion.Usa:
                        return "http://armory.worldofwarcraft.com";
                }
                return null;
            }
        }

        public  string              GetCharacterSheetData(string name)
        {
            return
                DownloadXmlPageValidated(
                    String.Format("character-sheet.xml?r={0}&n={1}", realmName, HttpUtility.UrlEncode(name)),
                    "characterTab", "CharacterSheet" + name);     
        }

        public string               GetCharacterTalentData(string name)
        {
            return
                DownloadXmlPageValidated(
                    String.Format("character-talents.xml?r={0}&n={1}", realmName, HttpUtility.UrlEncode(name)),
                    "talentTab", "CharacterTalents" + name);     
        }

        public int                  GetGuildInfoPageCount(string name)
        {
            // TODO: Conserve memory here, we create an xml document per call !:
            string          firstPage       = GetGuildInfoPageData(name, 0);

            if (firstPage != null )
            {
                XmlDocument document = new XmlDocument();
                document.LoadXml(firstPage);

                XmlAttribute maxPageAttribute =
                    document.SelectSingleNode("/page/guildInfo/guild/members/@maxPage") as XmlAttribute;

                if (maxPageAttribute != null)
                {
                    return int.Parse(maxPageAttribute.Value);
                }
            }

            return 0;
        }

        public  string              GetGuildInfoPageData(string name,int pageNumber)
        {
            return
                DownloadXmlPageValidated(
                    String.Format("guild-info.xml?r={0}&n={1}&p={2}", realmName, HttpUtility.UrlEncode(name), pageNumber + 1),
                    "rosterUrl", "GuildInfo" + name + "Page" + pageNumber.ToString());      
        }

        public string               GetItemInfoData(int id)
        {
            return
                DownloadXmlPageValidated(String.Format("item-info.xml?i={0}", id), "icon", "ItemInfo" + id.ToString());          
        }

        public string               GetItemTooltipData(int id)
        {
            return
                DownloadXmlPageValidated(String.Format("item-tooltip.xml?i={0}", id), "icon",
                                         "ItemTooltip" + id.ToString());     
        }

        public IList<Bitmap>        GetIconData(IconType type, object id)
        {
            switch (type)
            {
                case IconType.Item:
                    return DownloadItemIcon((ArmoryItemId)id);
                case IconType.Class:
                    return DownloadClassIcon((CharacterClass)id);
                case IconType.Race:
                    return DownloadRaceIcon((CharacterRace)id);
                case IconType.Faction:
                    return DownloadFactionIcon((CharacterFaction)id);
                case IconType.Gender:
                    return DownloadGenderIcon((CharacterGender)id);
                case IconType.Misc:
                    return DownloadMiscIcon((string)id);

            }
            return new List<Bitmap>();
        }

        private string              DownloadXmlPageValidated( string url,string validationTerm,string debugName )
        {
            string result = DownloadXmlPage(url);

            if ( !string.IsNullOrEmpty(result) )
            {
                if ( !result.Contains(validationTerm) )
                {
                    return null;
                }
                else
                {
                    WriteFile(debugName,result);
                    return result;
                }
            }
            return null;
        }
   
        private string              DownloadXmlPage(string url)
        {
            HttpWebRequest request      = CreateRequest(url);
            try
            {
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;

                StreamReader reader = new StreamReader(response.GetResponseStream(),Encoding.UTF8 );
                string result = reader.ReadToEnd();

                response.Close();

                return result;
            }
            catch
            {
                return null;
            }
        }

        private IList<Bitmap>       DownloadItemIcon(ArmoryItemId id)
        {       
            // TODO: Performance optimization, too much XmlDocument usage.
            XmlDocument document = new XmlDocument();
            document.LoadXml(GetItemInfoData(id.MainId));

            XmlAttribute iconAttribute = document.SelectSingleNode("/page/itemInfo/item/@icon") as XmlAttribute;
            if (iconAttribute != null)
            {
                string iconName = iconAttribute.Value;

                return DownloadMultiIconData(
                                                String.Format("images/icons/21x21/{0}.png", iconName),
                                                String.Format("images/icons/43x43/{0}.png", iconName),
                                                String.Format("images/icons/51x51/{0}.jpg", iconName),
                                                String.Format("images/icons/64x64/{0}.jpg", iconName));
            }

            return new List<Bitmap>();
        }

        private IList<Bitmap>       DownloadMiscIcon(string name)
        {
            return new List<Bitmap>();
        }

        private IList<Bitmap>       DownloadClassIcon(CharacterClass characterClass)
        {
            return DownloadMultiIconData( String.Format("images/icons/class/{0}.gif",(int)characterClass) );
        }

        private IList<Bitmap>       DownloadRaceIcon(CharacterRace race)
        {
            return DownloadMultiIconData( String.Format("images/icons/race/{0}-0.gif", (int)race));
        }

        private IList<Bitmap>       DownloadGenderIcon(CharacterGender gender)
        {
            return new List<Bitmap>();
        }

        private IList<Bitmap>       DownloadFactionIcon(CharacterFaction faction)
        {
            switch (faction)
            {
                case CharacterFaction.Alliance:
                    return DownloadMultiIconData( "images/icon-alliance.gif" );
                case CharacterFaction.Horde:
                    return DownloadMultiIconData( "images/icon-horde.gif" );
            }
            return new List<Bitmap>();
        }

        private IList<Bitmap>       DownloadMultiIconData(params String[] urls)
        {
            List<Bitmap> result = new List<Bitmap>();

            foreach( String url in urls )
            {
                Bitmap bitmap = DownloadSingleIconData(url);
                if (bitmap != null)
                {
                    result.Add(bitmap);
                }
            }
            return result;
        }

        private Bitmap              DownloadSingleIconData(string url)
        {
            HttpWebRequest  request = CreateRequest(url);
            try
            {
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    try
                    {
                        Bitmap bitmap = new Bitmap(response.GetResponseStream());
                        return bitmap;
                    }
                    catch
                    {
                        return null;
                    }
                    finally
                    {
                        response.Close();
                    }
                }
            }
            catch
            { }

            return null;
        }

        private HttpWebRequest      CreateRequest(string url)
        {
            String fullUrl = ServerUrl + "/" + url;
            HttpWebRequest request = WebRequest.Create(fullUrl) as HttpWebRequest;

            request.Headers.Remove("Accept-Language");
            request.Headers.Add("Accept-Language", culture.Name.ToLower());

            request.UserAgent =
                "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4";

            return request;
        }

        private void WriteFile(string name, string content)
        {
            if (!string.IsNullOrEmpty(debugPath))
            {
                if (!Directory.Exists(debugPath))
                {
                    Directory.CreateDirectory(debugPath);
                }
                string fullFilename = Path.Combine(debugPath, name + ".xml");

                if (!string.IsNullOrEmpty(content))
                {
                    File.WriteAllText(fullFilename, content);
                }
            }
        }

        public ArmoryServerDataSource(ArmoryServerRegion region, CultureInfo culture,string realmName,string debugPath )
        {
            this.region     = region;
            this.culture    = culture;
            this.realmName  = HttpUtility.UrlEncode(realmName);
            this.debugPath  = debugPath;
        }
    }
}
